// $Id: ImportHelper.cs 64 2008-05-06 18:29:47Z nvivo $

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Text;

namespace DBLGen
{
    /// <summary>
    /// Helps in the process of importing data to DBLGen. This class is meant to be
    /// used by import plugins.
    /// </summary>
    public class ImportHelper
    {
        public ImportHelper(DbProviderFactory providerFactory, string connectionString)
        {
            if (providerFactory == null)
                throw new ArgumentNullException("providerFactory");

            if (connectionString == null)
                throw new ArgumentNullException("connectionString");

            _providerFactory = providerFactory;
            _connectionString = connectionString;
        }

        private DbProviderFactory _providerFactory;
        private string _connectionString;

        /// <summary>
        /// Gets the DbProviderFactory associated with this helper.
        /// </summary>
        public DbProviderFactory ProviderFactory
        {
            get
            {
                return _providerFactory;
            }
        }

        /// <summary>
        /// Returns the connection string for this helper.
        /// </summary>
        protected string ConnectionString
        {
            get
            {
                return _connectionString;
            }
        }

        /// <summary>
        /// Creates a new database connection.
        /// </summary>
        /// <remarks>The connection is closed. You must remember to open and close it when using.</remarks>
        public DbConnection CreateConnection()
        {
            DbConnection connection = ProviderFactory.CreateConnection();
            connection.ConnectionString = _connectionString;

            return connection;
        }

        public string GetServerVersion()
        {
            DbConnection connection = CreateConnection();
            string version;

            try
            {
                connection.Open();
                version = connection.ServerVersion;
            }
            finally
            {
                connection.Close();
                connection.Dispose();
            }

            return version;
        }

        #region GetSchema

        /// <summary>
        /// Returns schema information for the current data provider applying the supplied restrictions.
        /// </summary>
        public DataTable GetSchema(string collectionName, string[] restrictions)
        {
            DataTable schema;
            DbConnection connection = CreateConnection();

            try
            {
                connection.Open();
                schema = connection.GetSchema(collectionName, restrictions);
            }
            finally
            {
                connection.Close();
                connection.Dispose();
            }

            return schema;
        }

        /// <summary>
        /// Returns schema information for the current data provider.
        /// </summary>
        public DataTable GetSchema(string collectionName)
        {
            return GetSchema(collectionName, null);
        }

        #endregion

        #region ExecuteDataTable

        /// <summary>
        /// Executes a command returns a DataTable.
        /// </summary>
        public DataTable ExecuteDataTable(DbCommand command)
        {
            DbDataAdapter adapter = ProviderFactory.CreateDataAdapter();
            DbConnection connection = CreateConnection();

            command.Connection = connection;
            adapter.SelectCommand = command;
            
            DataTable dt = new DataTable();
            adapter.Fill(dt);

            return dt;
        }

        /// <summary>
        /// Executes a text command and returns a DataTable.
        /// </summary>
        public DataTable ExecuteDataTable(string commandText)
        {
            DbCommand command = ProviderFactory.CreateCommand();
            command.CommandText = commandText;
            
            return ExecuteDataTable(command);
        }

        #endregion

        #region ExecuteReader

        /// <summary>
        /// Executes a command using a specified <see cref="CommandBehavior" />
        /// and returns a DbDataReader.
        /// </summary>
        /// <remarks>
        /// Every command is executed using the <see cref="CommandBehaviour.CloseConnection">CloseConnection</see>
        /// behavior, independently of the parameter passed. This is required to be able
        /// to close the connection by closing the reader.
        /// </remarks>
        public DbDataReader ExecuteReader(DbCommand command, CommandBehavior behavior)
        {
            DbConnection connection = CreateConnection();
            command.Connection = connection;

            DbDataReader reader;

            behavior &= CommandBehavior.CloseConnection;

            try
            {
                connection.Open();
                reader = command.ExecuteReader(behavior);
            }
            catch
            {
                connection.Close();
                connection.Dispose();
                throw;
            }

            return reader;
        }

        /// <summary>
        /// Executes a command and returns a DbDataReader.
        /// </summary>
        public DbDataReader ExecuteReader(DbCommand command)
        {
            return ExecuteReader(command, CommandBehavior.Default);
        }

        /// <summary>
        /// Executes a text command using the specified <see cref="CommandBehavior" />
        /// and returns a DbDataReader.
        /// </summary>
        public DbDataReader ExecuteReader(string commandText, CommandBehavior behavior)
        {
            DbCommand command = ProviderFactory.CreateCommand();
            command.CommandText = commandText;

            return ExecuteReader(command, behavior);
        }

        /// <summary>
        /// Executes a text command and returns a DbDataReader.
        /// </summary>
        public DbDataReader ExecuteReader(string commandText)
        {
            return ExecuteReader(commandText, CommandBehavior.Default);
        }

        #endregion

    }
}
